/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.music2;

import java.util.ArrayList;

import android.app.ExpandableListActivity;
import android.content.AsyncQueryHandler;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.database.sqlite.SQLiteException;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.MediaStore;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.SectionIndexer;
import android.widget.SimpleCursorTreeAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import com.android.music2.R;


public class PlaylistBrowserActivity extends ExpandableListActivity//ListActivity
    implements View.OnCreateContextMenuListener, MusicUtils.Defs
{
    private static final String TAG = "PlaylistBrowserActivity";
    private static final int DELETE_PLAYLIST = CHILD_MENU_BASE + 1;
    private static final int EDIT_PLAYLIST = CHILD_MENU_BASE + 2;
    private static final int RENAME_PLAYLIST = CHILD_MENU_BASE + 3;
    private static final int CHANGE_WEEKS = CHILD_MENU_BASE + 4;
    private static final int EXPORT_PLAYLIST = CHILD_MENU_BASE + 4;
    private static final int EXPORT_ALL_PLAYLISTS = CHILD_MENU_BASE + 20;
    
    private static final int CREATE_FOLDER = CHILD_MENU_BASE + 21;
    private static final int RENAME_FOLDER = CHILD_MENU_BASE + 22;
    private static final int DELETE_FOLDER = CHILD_MENU_BASE + 23;
    private static final int MOVE_TO_FOLDER = CHILD_MENU_BASE + 24;
    
    private static final long RECENTLY_ADDED_PLAYLIST = -1;
    private static final long ALL_SONGS_PLAYLIST = -2;
    private static final long PODCASTS_PLAYLIST = -3;
    private static final long UNRATED_PLAYLIST = -4;
    private static final long LAST_20_ADDED_PLAYLIST = -5;
    private static final long TOP_RATED_PLAYLIST = -6;
    private static final long MOST_PLAYED_PLAYLIST = -7;
    
    private static final int ID_AUTO_PLAYLISTS = 1;
    private static final int ID_MY_PLAYLISTS = 2;
    
    private PlaylistListAdapter mAdapter;
    boolean mAdapterSent;
    private static int mLastListPosCourse = -1;
    private static int mLastListPosFine = -1;

    private boolean mCreateShortcut;

    public PlaylistBrowserActivity()
    {
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);

        final Intent intent = getIntent();
        final String action = intent.getAction();
        if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
            mCreateShortcut = true;
        }

        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        MusicUtils.bindToService(this, new ServiceConnection() {
            public void onServiceConnected(ComponentName classname, IBinder obj) {
                if (Intent.ACTION_VIEW.equals(action)) {
                    long id = Long.parseLong(intent.getExtras().getString("playlist"));
                    if (id == RECENTLY_ADDED_PLAYLIST) {
                        playRecentlyAdded();
                    } else if (id == LAST_20_ADDED_PLAYLIST) {
                        playLast20Added();
                    } else if (id == PODCASTS_PLAYLIST) {
                        playPodcasts();
                    } else if (id == UNRATED_PLAYLIST) {
                        playUnrated2();
                    } else if (id == TOP_RATED_PLAYLIST) {
                        playTopRated();
                    } else if (id == MOST_PLAYED_PLAYLIST) {
                        playMostPlayed();
                    } else if (id == ALL_SONGS_PLAYLIST) {
                        long [] list = MusicUtils.getAllSongs(PlaylistBrowserActivity.this);
                        if (list != null) {
                            MusicUtils.playAll(PlaylistBrowserActivity.this, list, 0);
                        }
                    } else {
                        MusicUtils.playPlaylist(PlaylistBrowserActivity.this, id);
                    }
                    finish();
                    return;
                }
                MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
            }

            public void onServiceDisconnected(ComponentName classname) {
            	finish();
            }
        
        });
        IntentFilter f = new IntentFilter();
        f.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
        f.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
        f.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
        f.addDataScheme("file");
        registerReceiver(mScanListener, f);

        setContentView(R.layout.media_picker_activity_expanding);
        MusicUtils.updateButtonBar(this, R.id.playlisttab);
        ExpandableListView lv = getExpandableListView();
        lv.setOnCreateContextMenuListener(this);
        lv.setTextFilterEnabled(true);

        mAdapter = (PlaylistListAdapter) getLastNonConfigurationInstance();
        if (mAdapter == null) {
            //Log.i("@@@", "starting query");
            mAdapter = new PlaylistListAdapter(
                    getApplication(),
                    this,
                    null, // cursor
                    R.layout.track_list_item_group,
                    new String[] {},
                    new int[] {},
                    R.layout.track_list_item_child,
                    new String[] {},
                    new int[] {});
            
            setListAdapter(mAdapter);
            setTitle(R.string.working_playlists);
            
            //as we mock the cursor we dont need to run the query async, 
            //so call init with the provided cursor            
            //getPlaylistCursor(mAdapter.getQueryHandler(), null);
            init(getPlaylistCursor(null, null));
        } else {
            mAdapter.setActivity(this);
            setListAdapter(mAdapter);
            mPlaylistCursor = mAdapter.getCursor();
            // If mPlaylistCursor is null, this can be because it doesn't have
            // a cursor yet (because the initial query that sets its cursor
            // is still in progress), or because the query failed.
            // In order to not flash the error dialog at the user for the
            // first case, simply retry the query when the cursor is null.
            // Worst case, we end up doing the same query twice.
            if (mPlaylistCursor != null) {
                init(mPlaylistCursor);
            } else {
                setTitle(R.string.working_playlists);
                getPlaylistCursor(mAdapter.getQueryHandler(), null);
            }
        }
    }
    
    @Override
    public Object onRetainNonConfigurationInstance() {
        mAdapterSent = true;
        return mAdapter;
    }
    
    @Override
    public void onDestroy() {
    	ExpandableListView lv = getExpandableListView();
        if (lv != null) {
            mLastListPosCourse = lv.getFirstVisiblePosition();
            View cv = lv.getChildAt(0);
            if (cv != null) {
                mLastListPosFine = cv.getTop();
            }
        }
        MusicUtils.unbindFromService(this);
        if (!mAdapterSent) {
            Cursor c = mAdapter.getCursor();
            if (c != null) {
                c.close();
            }
        }        
        // Because we pass the adapter to the next activity, we need to make
        // sure it doesn't keep a reference to this activity. We can do this
        // by clearing its DatasetObservers, which setListAdapter(null) does.
        setListAdapter(null);
        mAdapter = null;
        unregisterReceiver(mScanListener);
        super.onDestroy();
    }
    
    @Override
    public void onResume() {
        super.onResume();
        IntentFilter f = new IntentFilter();
        f.addAction(MediaPlaybackService.META_CHANGED);
        f.addAction(MediaPlaybackService.QUEUE_CHANGED);
        registerReceiver(mTrackListListener, f);
        mTrackListListener.onReceive(null, null);
        
        MusicUtils.setSpinnerState(this);
        MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
    }
    @Override
    public void onPause() {
    	unregisterReceiver(mTrackListListener);
        mReScanHandler.removeCallbacksAndMessages(null);
        super.onPause();
    }
    private BroadcastReceiver mScanListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            MusicUtils.setSpinnerState(PlaylistBrowserActivity.this);
            mReScanHandler.sendEmptyMessage(0);
        }
    };
    private BroadcastReceiver mTrackListListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            getExpandableListView().invalidateViews();
            MusicUtils.updateNowPlaying(PlaylistBrowserActivity.this);
        }
    };
    
    private Handler mReScanHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (mAdapter != null) {
                getPlaylistCursor(mAdapter.getQueryHandler(), null);
            }
        }
    };
    public void init(Cursor cursor) {

        if (mAdapter == null) {
            return;
        }
        mAdapter.changeCursor(cursor);

        if (mPlaylistCursor == null) {
            MusicUtils.displayDatabaseError(this);
            closeContextMenu();
            mReScanHandler.sendEmptyMessageDelayed(0, 1000);
            return;
        }

        // restore previous position
        if (mLastListPosCourse >= 0) {
        	getExpandableListView().setSelectionFromTop(mLastListPosCourse, mLastListPosFine);
            mLastListPosCourse = -1;
        }
        MusicUtils.hideDatabaseError(this);
        MusicUtils.updateButtonBar(this, R.id.playlisttab);
        setTitle();
    }

    private void setTitle() {
        setTitle(R.string.playlists_title);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!mCreateShortcut) {
            menu.add(0, PARTY_SHUFFLE, 0, R.string.party_shuffle); // icon will be set in onPrepareOptionsMenu()
        }
        //menu.add(1, NEW_PLAYLIST, 0, R.string.new_playlist).setIcon(android.R.drawable.ic_menu_add);
        menu.add(1, CREATE_FOLDER, 0, R.string.new_playlist_folder).setIcon(android.R.drawable.ic_menu_add);
        menu.add(0, EXPORT_ALL_PLAYLISTS, 0, R.string.export_all).setIcon(android.R.drawable.ic_menu_save);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MusicUtils.setPartyShuffleMenuIcon(menu);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Intent intent;
        switch (item.getItemId()) {
            case PARTY_SHUFFLE:
                MusicUtils.togglePartyShuffle();
                break;
            case NEW_PLAYLIST: {
                intent = new Intent();
                intent.setClass(this, CreatePlaylist.class);
                startActivityForResult(intent, NEW_PLAYLIST);
                return true;
            }
            case CREATE_FOLDER: {
            	intent = new Intent();
            	intent.setClass(this, CreateFolder.class);
            	startActivityForResult(intent, CREATE_FOLDER);
                return true;
            }
            case EXPORT_ALL_PLAYLISTS:
                MusicUtils.exportAllPlaylists(this);
                break;
            }
        return super.onOptionsItemSelected(item);
    }
    
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfoIn) {
        if (mCreateShortcut) {
            return;
        }

        ExpandableListContextMenuInfo mi = (ExpandableListContextMenuInfo) menuInfoIn;
        
        int itemtype = ExpandableListView.getPackedPositionType(mi.packedPosition);
        int gpos = ExpandableListView.getPackedPositionGroup(mi.packedPosition);
        int cpos = ExpandableListView.getPackedPositionChild(mi.packedPosition);
        
        if (itemtype == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
            if (gpos == -1) {
                // this shouldn't happen
                Log.d("Artist/Album", "no group");
                return;
            }
            gpos = gpos - getExpandableListView().getHeaderViewsCount();
            mPlaylistCursor.moveToPosition(gpos);
            //For not auto playlists folder, add the extra options
            if(mPlaylistCursor.getInt(mPlaylistCursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists._ID)) != ID_AUTO_PLAYLISTS) {
            	menu.add(0, NEW_PLAYLIST, 0, R.string.new_playlist);
            	menu.add(0, EXPORT_ALL_PLAYLISTS, 0, R.string.export_all);
            	menu.add(0, RENAME_FOLDER, 0, R.string.rename_folder_menu);
            	menu.add(0, DELETE_FOLDER, 0, R.string.delete_folder_menu);
            }
            menu.setHeaderTitle(mPlaylistCursor.getString(mPlaylistCursor.getColumnIndexOrThrow(
                    MediaStore.Audio.Playlists.NAME)));
            return;
        } else if (itemtype == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
            if (cpos == -1) {
                // this shouldn't happen
                Log.d("Artist/Album", "no child");
                return;
            }
            Cursor c = (Cursor) getExpandableListAdapter().getChild(gpos, cpos);
            c.moveToPosition(cpos);

            gpos = gpos - getExpandableListView().getHeaderViewsCount();
            mPlaylistCursor.moveToPosition(gpos);
            
            menu.add(0, PLAY_SELECTION, 0, R.string.play_selection);

            if (mi.id >= 0) {
                menu.add(0, DELETE_PLAYLIST, 0, R.string.delete_playlist_menu);
                menu.add(0, RENAME_PLAYLIST, 0, R.string.rename_playlist_menu);
                menu.add(0, EXPORT_PLAYLIST, 0, R.string.export_playlist_menu);
                SubMenu sub = menu.addSubMenu(0, MOVE_TO_FOLDER, 0, R.string.move_to_folder);
                //Get this folder name
                String name = mPlaylistCursor.getString(mPlaylistCursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.NAME));
                MusicUtils.makeFolderMenu(this, sub, mi.id, name);
            }

            if (mi.id == RECENTLY_ADDED_PLAYLIST) {
                menu.add(0, EDIT_PLAYLIST, 0, R.string.edit_playlist_menu);
            }

            //mPlaylistCursor.moveToPosition(mi.position);
            //use mPlaylistCursor here to get name of group...
            menu.setHeaderTitle(c.getString(c.getColumnIndexOrThrow(
                    MediaStore.Audio.Playlists.NAME)));

        }
        


    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        //AdapterContextMenuInfo mi = (AdapterContextMenuInfo) item.getMenuInfo();
        ExpandableListContextMenuInfo mi = (ExpandableListContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) {
            case PLAY_SELECTION:
                if (mi.id == RECENTLY_ADDED_PLAYLIST) {
                    playRecentlyAdded();
                } else if (mi.id == LAST_20_ADDED_PLAYLIST) {
                    playLast20Added();
                } else if (mi.id == PODCASTS_PLAYLIST) {
                    playPodcasts();
                } else if (mi.id == UNRATED_PLAYLIST) {
                    playUnrated2();
                } else if (mi.id == TOP_RATED_PLAYLIST) {
                    playTopRated();
                } else if (mi.id == MOST_PLAYED_PLAYLIST) {
                    playMostPlayed();
                } else {
                    MusicUtils.playPlaylist(this, mi.id);
                }
                break;
            case EXPORT_PLAYLIST:
            	MusicUtils.exportPlaylist(this, mi.id, true);
            	break;
            case EXPORT_ALL_PLAYLISTS:
            	MusicUtils.exportAllPlaylists(this);
            	break;
            case DELETE_PLAYLIST:
                //Delete it from the audio_playlists table
            	Uri uri = ContentUris.withAppendedId(
                        MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, mi.id);
                getContentResolver().delete(uri, null, null);
                
                //Delete it from the playlist_folder_map table
        		getContentResolver().delete(
        				ExtendedAudioProvider.CONTENT_URI_FOLDERS_MAP, 
        				ExtendedAudioProvider._ID + "=" + mi.id, 
        				null);                 
                
                Toast.makeText(this, R.string.playlist_deleted_message, Toast.LENGTH_SHORT).show();
                if (mPlaylistCursor.getCount() == 0) {
                    setTitle(R.string.no_playlists_title);
                }
                break;
            case EDIT_PLAYLIST:
                if (mi.id == RECENTLY_ADDED_PLAYLIST) {
                    Intent intent = new Intent();
                    intent.setClass(this, WeekSelector.class);
                    startActivityForResult(intent, CHANGE_WEEKS);
                    return true;
                } else {
                    Log.e(TAG, "should not be here");
                }
                break;
            case RENAME_PLAYLIST:
                Intent intent = new Intent();
                intent.setClass(this, RenameItemActivity.class);
                intent.putExtra("type", RenameItemActivity.RENAME_PLAYLIST);
                intent.putExtra("rename", mi.id);
                intent.putExtra("original",getPlaylistName(mi.id)); //item.getTitle is "rename" ie the context menu item
                startActivityForResult(intent, RENAME_PLAYLIST);
                break;
            case RENAME_FOLDER:            	
                Intent intent1 = new Intent();
                intent1.setClass(this, RenameItemActivity.class);
                intent1.putExtra("type", RenameItemActivity.RENAME_FOLDER);
                intent1.putExtra("rename", mi.id);
                intent1.putExtra("original",getFolderName(mi.id)); //item.getTitle is "rename" ie the context menu item
                startActivityForResult(intent1, RENAME_PLAYLIST);
            	break;
            case DELETE_FOLDER:
            	MusicUtils.deleteFolder(this, mi.id);
            	break;
            case NEW_PLAYLIST:          
            	intent = new Intent();
            	intent.setClass(this, CreatePlaylist.class);
            	intent.putExtra("folderId", mi.id);
            	startActivityForResult(intent, NEW_PLAYLIST);
            	break;
            case FOLDER_SELECTED:            	
            	long folderId = item.getIntent().getLongExtra("folder", 0);
            	long plid = item.getIntent().getLongExtra("playlist", 0);
            	if(folderId > 0) {
            		MusicUtils.movePlaylistToFolder(this, plid, folderId);
            		Toast.makeText(this, "Playlist Moved", Toast.LENGTH_SHORT).show();
            	}
            	break;
        }
        return true;
    }

    private String getPlaylistName(long id) {
    	Cursor c = MusicUtils.query(this, MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
              new String[] { MediaStore.Audio.Playlists.NAME },
              MediaStore.Audio.Playlists._ID + "=?",
              new String[] { Long.valueOf(id).toString()},
              MediaStore.Audio.Playlists.NAME);
	      String name = null;
	      if (c != null) {
	          c.moveToFirst();
	          if (!c.isAfterLast()) {
	              name = c.getString(0);
	          }
	      }
	      c.close();
	      return name;
    }
    
    private String getFolderName(long id) {
    	Cursor c = MusicUtils.query(this, ExtendedAudioProvider.CONTENT_URI_FOLDERS,
              new String[] { ExtendedAudioProvider.FOLDER_NAME },
              ExtendedAudioProvider._ID + "=?",
              new String[] { Long.valueOf(id).toString()},
              ExtendedAudioProvider.FOLDER_NAME);
	      String name = null;
	      if (c != null) {
	          c.moveToFirst();
	          if (!c.isAfterLast()) {
	              name = c.getString(0);
	          }
	      }
	      c.close();
	      return name;
    }
    
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        switch (requestCode) {
            case SCAN_DONE:
                if (resultCode == RESULT_CANCELED) {
                    finish();
                } else if (mAdapter != null) {
                    getPlaylistCursor(mAdapter.getQueryHandler(), null);
                }
                break;
        }
    }
    
    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)
    {
        if (mCreateShortcut) {
            final Intent shortcut = new Intent();
            shortcut.setAction(Intent.ACTION_VIEW);
            shortcut.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/playlist");
            shortcut.putExtra("playlist", String.valueOf(id));

            final Intent intent = new Intent();
            intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcut);
            intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, ((TextView) v.findViewById(R.id.line1)).getText());
            intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(
                    this, R.drawable.ic_launcher_shortcut_music_playlist));

            setResult(RESULT_OK, intent);
            finish();
            return true;
        }
        
        if (id == RECENTLY_ADDED_PLAYLIST) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", "recentlyadded");
            startActivity(intent);
        } else if (id == LAST_20_ADDED_PLAYLIST) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", "last20added");
            startActivity(intent);
        } else if (id == PODCASTS_PLAYLIST) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", "podcasts");
            startActivity(intent);
        } else if (id == UNRATED_PLAYLIST) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", "unrated");
            startActivity(intent);
        } else if (id == TOP_RATED_PLAYLIST) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", "topRated");
            startActivity(intent);
        } else if (id == MOST_PLAYED_PLAYLIST) {
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", "mostPlayed");
            startActivity(intent);
        } else {
            Intent intent = new Intent(Intent.ACTION_EDIT);
            intent.setDataAndType(Uri.EMPTY, "vnd.android.cursor.dir/track");
            intent.putExtra("playlist", Long.valueOf(id).toString());
            startActivity(intent);
        }
        return true;
    }

    private void playRecentlyAdded() {
        // do a query for all songs added in the last X weeks
        int X = MusicUtils.getIntPref(this, "numweeks", 2) * (3600 * 24 * 7);
        final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
        String where = MediaStore.MediaColumns.DATE_ADDED + ">" + (System.currentTimeMillis() / 1000 - X);
        Cursor cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                ccols, where, null, MediaStore.MediaColumns.DATE_ADDED);
        
        if (cursor == null) {
            // Todo: show a message
            return;
        }
        try {
            int len = cursor.getCount();
            long [] list = new long[len];
            for (int i = 0; i < len; i++) {
                cursor.moveToNext();
                list[i] = cursor.getLong(0);
            }
            MusicUtils.playAll(this, list, 0);
        } catch (SQLiteException ex) {
        } finally {
            cursor.close();
        }
    }
    
    private void playLast20Added() {
    	final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
        // do a query for the last 20 songs added
        Cursor cursor = MusicUtils.query(this, 
        		MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 
        		ccols, 
        		MediaStore.Audio.Media.IS_MUSIC + "=1", 
        		null, 
        		MediaStore.Audio.Media.DATE_ADDED + " DESC", 
        		20);  
        
        if (cursor == null) {
            // Todo: show a message
            return;
        }
        try {
            int len = cursor.getCount();
            long [] list = new long[len];
            for (int i = 0; i < len; i++) {
                cursor.moveToNext();
                list[i] = cursor.getLong(0);
            }
            MusicUtils.playAll(this, list, 0);
        } catch (SQLiteException ex) {
        } finally {
            cursor.close();
        }
    }

    private void playPodcasts() {
        // do a query for all files that are podcasts
        final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
        Cursor cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                ccols, "is_podcast" + "=1",
                null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        
        if (cursor == null) {
            // TODO: show a message
            return;
        }
        try {
            int len = cursor.getCount();
            long [] list = new long[len];
            for (int i = 0; i < len; i++) {
                cursor.moveToNext();
                list[i] = cursor.getLong(0);
            }
            MusicUtils.playAll(this, list, 0);
        } catch (SQLiteException ex) {
        } finally {
            cursor.close();
        }
    }

    
    private void playUnrated2() {
    	Cursor cursor = MusicUtils.getUnratedTracks(this, false);
       
        //Create the list of song ids we actually want to play
        if (cursor == null) {
            // TODO: show a message
            return;
        }
        try {
            int len = cursor.getCount();
            long [] unratedlist = new long[len];
            for (int i = 0; i < len; i++) {
                cursor.moveToNext();
                unratedlist[i] = cursor.getLong(0);
            }
            MusicUtils.playAll(this, unratedlist, 0);
        } catch (SQLiteException ex) {
        } finally {
            cursor.close();
        }
  
    }
    
    private void playTopRated() {
    	Cursor cursor = MusicUtils.getTopRatedTracks(this, false);
       
        //Create the list of song ids we actually want to play
        if (cursor == null) {
            // TODO: show a message
            return;
        }
        try {
            int len = cursor.getCount();
            long [] list = new long[len];
            for (int i = 0; i < len; i++) {
                cursor.moveToNext();
                list[i] = cursor.getLong(0);
            }
            MusicUtils.playAll(this, list, 0);
        } catch (SQLiteException ex) {
        } finally {
            cursor.close();
        }
  
    }
    
    private void playMostPlayed() {
    	try {
    	Cursor cursor = MusicUtils.getMostPlayedTracks(this, false);
    	
        //Create the list of song ids we actually want to play
        if (cursor == null) {
            // TODO: show a message
            return;
        }
        try {
            int len = cursor.getCount();
            long [] list = new long[len];
            for (int i = 0; i < len; i++) {
                cursor.moveToNext();
                list[i] = cursor.getLong(0);
            }
            MusicUtils.playAll(this, list, 0);
        } catch (SQLiteException ex) {
        	Toast.makeText(this, "PBA.PMP1:" + ex.getMessage(), Toast.LENGTH_SHORT).show();
        } finally {
            cursor.close();
        }
    	} catch (Exception e) {
    		Toast.makeText(this, "PBA.PMP2:" + e.getMessage(), Toast.LENGTH_SHORT).show();
    	}
  
    }
    
    /***
     * See also playUnrated2 for alternative method
     */
    private void playUnrated() {   	
    	
    	// do a query for all files that are unrated
        final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
        
        //firstly find all the audio that is_music
        Cursor cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                ccols, MediaStore.Audio.Media.IS_MUSIC + "=1",
                null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        
        //Get the number of tracks that are rated
        Cursor ratedCursor = MusicUtils.query(this, ExtendedAudioProvider.CONTENT_URI_SONGS,
    		  new String[] { ExtendedAudioProvider._ID}, ExtendedAudioProvider.RATING + ">0", null, null);
              
        //Work out the number of unrated tracks
        int numUnrated = cursor.getCount() - ratedCursor.getCount();
        
        //If multiple, work out the list and play them
        if(numUnrated == 0) {
        	Toast.makeText(this, "No unrated tracks", Toast.LENGTH_SHORT).show();
        } else {
        	try {
	        	long[] unratedList = new long[numUnrated];
	            int len = cursor.getCount();
	            int numberAdded = 0;
	            
	            //loop through each song and find if its rated, 0 will be returned if not or is 0
	            for (int i = 0; i < len; i++) {
	                cursor.moveToNext();
	                
	                int currentItemRating = MusicUtils.getCurrentRating(this, cursor.getLong(0));
	                if(currentItemRating == 0) {
	                	unratedList[numberAdded] = cursor.getLong(0);
	                	numberAdded++;
	                }                
	            }
	            MusicUtils.playAll(this, unratedList, 0);
        	} catch (SQLiteException ex) {
        	} finally {
        		cursor.close();
        	}
        }

    }
    
    String[] mCols = new String[] {
            MediaStore.Audio.Playlists._ID,
            MediaStore.Audio.Playlists.NAME
    };

    
    /***
     * The group cursor is the playlist folders - child cursors are based on the group id
     * @param async
     * @param filterstring
     * @return
     */
    private Cursor getPlaylistCursor(AsyncQueryHandler async, String filterstring) {

//        MatrixCursor autoCursor = new MatrixCursor(mCols);
//        autoCursor.addRow(new Object[] {ID_AUTO_PLAYLISTS, "Auto Playlists"});
//        autoCursor.addRow(new Object[] {ID_MY_PLAYLISTS, "My Playlists"});
//        return autoCursor;        
        
        return MusicUtils.query(this, ExtendedAudioProvider.CONTENT_URI_FOLDERS,
                new String[] {ExtendedAudioProvider._ID, ExtendedAudioProvider.FOLDER_NAME }, 
                null, null, null);

    }
    
    static class PlaylistListAdapter extends SimpleCursorTreeAdapter implements SectionIndexer {
    	
        int mTitleIdx;
        int mIdIdx;
        private PlaylistBrowserActivity mActivity = null;
        private AsyncQueryHandler mQueryHandler;
        private String mConstraint = null;
        private boolean mConstraintIsValid = false;
        private MusicAlphabetIndexer mIndexer;
        //private final Context mContext;
        //private final Drawable mNowPlayingOverlay;
        
        static class ViewHolder {
            TextView line1;
            TextView line2;
            ImageView play_indicator;
            ImageView icon;
            RatingBar rating;
        }

        class QueryHandler extends AsyncQueryHandler {
            QueryHandler(ContentResolver res) {
                super(res);
            }
            
            @Override
            protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
                //Log.i("@@@", "query complete: " + cursor.getCount() + "   " + mActivity);
                mActivity.init(cursor);
            }
        }

        @Override
        protected Cursor getChildrenCursor(Cursor groupCursor) {
        	
            String[] mCols = new String[] {
                    MediaStore.Audio.Playlists._ID,
                    MediaStore.Audio.Playlists.NAME
            };
        	
        	int folderId = groupCursor.getInt(mIdIdx);
        	if(folderId == ID_AUTO_PLAYLISTS) {
        		//Manually crate the playlist list
        		MatrixCursor autoPlaylists = new MatrixCursor(mCols);
        		autoPlaylists.addRow(new Object[] {RECENTLY_ADDED_PLAYLIST, "Recently Added"});
        		autoPlaylists.addRow(new Object[] {LAST_20_ADDED_PLAYLIST, "Last 20 Added"});
        		autoPlaylists.addRow(new Object[] {UNRATED_PLAYLIST, "Unrated"});
        		autoPlaylists.addRow(new Object[] {TOP_RATED_PLAYLIST, "Top Rated"});
        		autoPlaylists.addRow(new Object[] {MOST_PLAYED_PLAYLIST, "Most Played"});
        		
                // check if there are any podcasts
                Cursor counter = MusicUtils.query(mActivity, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                        new String[] {"count(*)"}, "is_podcast=1", null, null);
                if (counter != null) {
                    counter.moveToFirst();
                    int numpodcasts = counter.getInt(0);
                    counter.close();
                    if (numpodcasts > 0) {
                    	autoPlaylists.addRow(new Object[] {PODCASTS_PLAYLIST, "Podcasts"});
                    }
                }
        		
        		
        		return autoPlaylists;
        	} else {
	            //Query the database for all playlists in this folder
	            StringBuilder where = new StringBuilder();
	            where.append(ExtendedAudioProvider.FOLDER_ID + "=" + folderId );
	            String whereclause = where.toString();
	
	            Cursor c = null;
	            c = MusicUtils.query(mActivity, ExtendedAudioProvider.CONTENT_URI_FOLDERS_MAP,
	                    mCols, whereclause, null, ExtendedAudioProvider.PLAYLIST_NAME);
	            return c;
        	}
      
        }

        PlaylistListAdapter(Context context, PlaylistBrowserActivity currentactivity,
                Cursor cursor, int glayout, String[] gfrom, int[] gto, 
                int clayout, String[] cfrom, int[] cto) {
            super(context, cursor, glayout, gfrom, gto, clayout, cfrom, cto);
            mActivity = currentactivity;
            getColumnIndices(cursor);
            mQueryHandler = new QueryHandler(context.getContentResolver());
            //mContext = context;
            //Resources r = context.getResources();
            //mNowPlayingOverlay = r.getDrawable(R.drawable.indicator_ic_mp_playing_list);
        }
        
        
        private void getColumnIndices(Cursor cursor) {
            if (cursor != null) {
                mTitleIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.NAME);
                mIdIdx = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists._ID);
                if (mIndexer != null) {
                    mIndexer.setCursor(cursor);
                } else {
                    mIndexer = new MusicAlphabetIndexer(cursor, mTitleIdx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
                }
            }
        }

        public void setActivity(PlaylistBrowserActivity newactivity) {
            mActivity = newactivity;
        }
        
        public AsyncQueryHandler getQueryHandler() {
            return mQueryHandler;
        }

        @Override
        public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
            View v = super.newGroupView(context, cursor, isExpanded, parent);
            ImageView iv = (ImageView) v.findViewById(R.id.icon);
            ViewGroup.LayoutParams p = iv.getLayoutParams();
            p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
            p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            ViewHolder vh = new ViewHolder();
            vh.line1 = (TextView) v.findViewById(R.id.line1);
            vh.line2 = (TextView) v.findViewById(R.id.line2);
            vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
            vh.icon = (ImageView) v.findViewById(R.id.icon);
            vh.icon.setPadding(0, 0, 1, 0);
            vh.rating = (RatingBar) v.findViewById(R.id.item_rating);
            v.setTag(vh);
            return v;
        }

        @Override
        public View newChildView(Context context, Cursor cursor, boolean isLastChild,
                ViewGroup parent) {
            View v = super.newChildView(context, cursor, isLastChild, parent);
            ViewHolder vh = new ViewHolder();
            vh.line1 = (TextView) v.findViewById(R.id.line1);
            vh.line2 = (TextView) v.findViewById(R.id.line2);
            vh.play_indicator = (ImageView) v.findViewById(R.id.play_indicator);
            vh.icon = (ImageView) v.findViewById(R.id.icon);
            //vh.icon.setBackgroundDrawable(mDefaultAlbumIcon);
            vh.icon.setPadding(0, 0, 1, 0);
            vh.rating = (RatingBar) v.findViewById(R.id.item_rating);
            v.setTag(vh);
            return v;
        }

        @Override
        public void bindGroupView(View view, Context context, Cursor cursor, boolean isexpanded) {

            ViewHolder vh = (ViewHolder) view.getTag();
           
            String folderName = cursor.getString(mTitleIdx);            
            vh.line1.setText(folderName);

            if(folderName.equals("Auto Playlists")) {
            	int numAutoPlaylists = getChildrenCursor(cursor).getCount();
                String num_playlists = "";
                if(numAutoPlaylists == 0 ) {
                	num_playlists = "No auto playlists";
                } else if(numAutoPlaylists == 1) {
                	num_playlists = "1 auto playlist";
                } else {
                	num_playlists = String.valueOf(numAutoPlaylists) + " auto playlists";
                }
                vh.line2.setText(num_playlists);
            } else {
	            int numPlaylists = getChildrenCursor(cursor).getCount();
	            String num_playlists = "";
	            if(numPlaylists == 0 ) {
	            	num_playlists = "No playlists";
	            } else if(numPlaylists == 1) {
	            	num_playlists = "1 playlist";
	            } else {
	            	num_playlists = String.valueOf(numPlaylists) + " playlists";
	            }
	            vh.line2.setText(num_playlists);
            }
                       
            vh.play_indicator.setVisibility(View.INVISIBLE);
            vh.rating.setVisibility(View.INVISIBLE);
        }
        
        @Override
        public void bindChildView(View view, Context context, Cursor cursor, boolean islast) {
            
            TextView tv = (TextView) view.findViewById(R.id.line1);
            
            String name = cursor.getString(mTitleIdx);
            tv.setText(name);
            
            long id = cursor.getLong(mIdIdx);            
            ImageView iv = (ImageView) view.findViewById(R.id.icon);
            if (id == RECENTLY_ADDED_PLAYLIST || id == LAST_20_ADDED_PLAYLIST) {
                iv.setImageResource(R.drawable.ic_mp_playlist_recently_added_list);
            } else {
                iv.setImageResource(R.drawable.ic_mp_playlist_list);
            }
            ViewGroup.LayoutParams p = iv.getLayoutParams();
            p.width = ViewGroup.LayoutParams.WRAP_CONTENT;
            p.height = ViewGroup.LayoutParams.WRAP_CONTENT;

            iv = (ImageView) view.findViewById(R.id.play_indicator);
            iv.setVisibility(View.GONE);

            view.findViewById(R.id.line2).setVisibility(View.GONE);
            
            view.findViewById(R.id.item_rating).setVisibility(View.GONE);
        }

        @Override
        public void changeCursor(Cursor cursor) {
            if (cursor != mActivity.mPlaylistCursor) {
                mActivity.mPlaylistCursor = cursor;
                super.changeCursor(cursor);
                getColumnIndices(cursor);
            }
        }
        
        public Object[] getSections() {
            return mIndexer.getSections();
        }
        
        public int getPositionForSection(int sectionIndex) {
            return mIndexer.getPositionForSection(sectionIndex);
        }
        
        public int getSectionForPosition(int position) {
            return 0;
        }
        
        @Override
        public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
            String s = constraint.toString();
            if (mConstraintIsValid && (
                    (s == null && mConstraint == null) ||
                    (s != null && s.equals(mConstraint)))) {
                return getCursor();
            }
            Cursor c = mActivity.getPlaylistCursor(null, s);
            mConstraint = s;
            mConstraintIsValid = true;
            return c;
        }
    }
    
    private Cursor mPlaylistCursor;
}

